import { ElTableColumn, ElSkeleton } from "element-plus";
import type { TableColumn } from "@/types/table";
import defaultStyle from "@/config/defaultConfig";
import CommonTag from "@/components/CommonTag.vue";
import { useUrlDictStore } from "@/store";
import { getDicurlMap } from "@/utils";

export default defineComponent({
  name: "RenderColumn",
  inheritAttrs: false,
  props: {
    column: {
      type: Array as () => TableColumn[],
      default: [],
    },
  },
  setup(props, { slots }) {
    const loading = ref(true);
    const urlDictStore = useUrlDictStore();

    onMounted(() => {
      function traverseColumns(cols: TableColumn[]) {
        cols.forEach((col) => {
          if (hasChildren(col)) {
            traverseColumns(col.children);
          } else {
            if (col["dicUrl"]) requests.push(urlDictStore.fetchUrl(col["dicUrl"]));
          }
        });
      }
      const requests: Promise<Custom.TreeData | undefined>[] = [];
      traverseColumns(props.column);
      loading.value = true;
      (async () => {
        await Promise.all(requests);
        loading.value = false;
      })();
    });

    function hasChildren(menu: TableColumn): menu is TableColumn & { children: TableColumn[] } {
      return !!(menu.children && menu.children?.length > 0);
    }

    function createSlotContent(options: {
      prop?: string;
      slot?: boolean;
      slotHeader?: boolean;
      slotExpand?: boolean;
      tag?: boolean;
      map?: Record<string, string>;
      colorDict?: Record<string, Custom.TagType>;
      copy?: boolean;
      multiple?: boolean;
    }) {
      const {
        prop = "",
        slot = false,
        slotHeader = false,
        slotExpand = false,
        tag = false,
        copy = false,
        map,
        colorDict,
        multiple,
      } = options;
      if (slot || slotExpand || slotHeader || tag || copy) {
        let res: Record<string, unknown> = {};
        if (copy)
          res["default"] = (scope: { row: Record<string, string | number> }) => {
            let value = scope.row[prop];
            return <span v-copy={value}>{value}</span>;
          };
        if (tag)
          res["default"] = (scope: { row: Record<string, string | number> }) => {
            let value = scope.row[prop];
            return (
              <CommonTag
                value={value!}
                labelDict={map}
                colorDict={colorDict}
                size={multiple ? "small" : "default"}
              ></CommonTag>
            );
          };
        if (slot) res["default"] = (scope: unknown) => slots[prop!]?.(scope);
        if (slotHeader) res["header"] = (scope: unknown) => slots[`${prop}-header`]?.(scope);
        if (slotExpand) res["expand"] = (scope: unknown) => slots[`${prop}-expand`]?.(scope);
        return res;
      } else return undefined;
    }

    function columnItem(cols: TableColumn[]) {
      return cols
        .filter((item) => !item?.hide)
        .map((item: TableColumn) => {
          const {
            children,
            slot,
            slotExpand,
            slotHeader,
            type,
            dicData,
            dicUrl,
            multiple,
            props: labelMap,
            align = defaultStyle.TableAlign,
            headerAlign = defaultStyle.TableAlign,
            ...columnProps
          } = item;
          let map: Record<string, string> = {};
          // console.log("---map: ", item.label);
          if (!columnProps.formatter && ("select" === type || "tree" === type)) {
            let key = labelMap?.value ?? "value";
            let val = labelMap?.label ?? "label";
            if (dicData) {
              map = Object.fromEntries(dicData.map((item) => [item[key], item[val]]));
            }
            if (dicUrl) {
              map = getDicurlMap(urlDictStore.dictData.get(dicUrl), key, val);
              console.log("----dicurl: ", map);
            }
            let fmt = (
              _row: unknown,
              _column: unknown,
              cellValue: string | number,
              _index: number
            ) => {
              return multiple
                ? String(cellValue)
                    .split(",")
                    .map((v) => map[v])
                    .join()
                : (map[cellValue] ?? "--");
            };
            columnProps["formatter"] = fmt;
          }
          if (hasChildren(item)) {
            return (
              <ElTableColumn {...columnProps} align={align} headerAlign={headerAlign}>
                {columnItem(item.children)}
              </ElTableColumn>
            );
          } else {
            return (
              <ElTableColumn {...columnProps} align={align} headerAlign={headerAlign}>
                {createSlotContent({ ...item, map })}
              </ElTableColumn>
            );
          }
        });
    }
    const tabelColumn = computed(() => {
      if (loading.value) {
        return props.column
          .filter((item) => !item?.hide)
          .map((item) => (
            <ElTableColumn
              key={item.prop}
              {...item}
              v-slots={{ default: () => <ElSkeleton rows={0} /> }}
            ></ElTableColumn>
          ));
      } else {
        return columnItem(props.column);
      }
    });
    // const renderRes = columnItem(props.column);
    return () => tabelColumn.value;
  },
});
